home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0992.ARJ / MESSAGE.C < prev    next >
Text File  |  1992-07-29  |  19KB  |  636 lines

  1. /* --------- message.c ---------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int px = -1, py = -1;
  6. static int pmx = -1, pmy = -1;
  7. static int mx, my;
  8. static int handshaking = 0;
  9. static BOOL CriticalError;
  10. BOOL AllocTesting = FALSE;
  11. jmp_buf AllocError;
  12.  
  13. /* ---------- event queue ---------- */
  14. static struct events    {
  15.     MESSAGE event;
  16.     int mx;
  17.     int my;
  18. } EventQueue[MAXMESSAGES];
  19.  
  20. /* ---------- message queue --------- */
  21. static struct msgs {
  22.     WINDOW wnd;
  23.     MESSAGE msg;
  24.     PARAM p1;
  25.     PARAM p2;
  26. } MsgQueue[MAXMESSAGES];
  27.  
  28. static int EventQueueOnCtr;
  29. static int EventQueueOffCtr;
  30. static int EventQueueCtr;
  31.  
  32. static int MsgQueueOnCtr;
  33. static int MsgQueueOffCtr;
  34. static int MsgQueueCtr;
  35.  
  36. static int lagdelay = FIRSTDELAY;
  37.  
  38. static void (interrupt far *oldtimer)(void);
  39. static void (interrupt far *oldkeyboard)(void);
  40.  
  41. static int keyportvalue;    /* for watching for key release */
  42.  
  43. WINDOW CaptureMouse;
  44. WINDOW CaptureKeyboard;
  45. static BOOL NoChildCaptureMouse;
  46. static BOOL NoChildCaptureKeyboard;
  47.  
  48. static int doubletimer = -1;
  49. static int delaytimer  = -1;
  50. static int clocktimer  = -1;
  51.  
  52. static WINDOW Cwnd;
  53.  
  54. static void interrupt far newkeyboard(void)
  55. {
  56.     keyportvalue = inp(KEYBOARDPORT);
  57.     oldkeyboard();
  58. }
  59.  
  60. /* ------- timer interrupt service routine ------- */
  61. static void interrupt far newtimer(void)
  62. {
  63.     if (timer_running(doubletimer))
  64.         countdown(doubletimer);
  65.     if (timer_running(delaytimer))
  66.         countdown(delaytimer);
  67.     if (timer_running(clocktimer))
  68.         countdown(clocktimer);
  69.     oldtimer();
  70. }
  71.  
  72. static char ermsg[] = "Error accessing drive x";
  73.  
  74. /* -------- test for critical errors --------- */
  75. int TestCriticalError(void)
  76. {
  77.     int rtn = 0;
  78.     if (CriticalError)    {
  79.         rtn = 1;
  80.         CriticalError = FALSE;
  81.         if (TestErrorMessage(ermsg) == FALSE)
  82.             rtn = 2;
  83.     }
  84.     return rtn;
  85. }
  86.  
  87. /* ------ critical error interrupt service routine ------ */
  88. static void interrupt far newcrit(IREGS ir)
  89. {
  90.     if (!(ir.ax & 0x8000))     {
  91.         ermsg[sizeof(ermsg) - 2] = (ir.ax & 0xff) + 'A';
  92.         CriticalError = TRUE;
  93.     }
  94.     ir.ax = 0;
  95. }
  96.  
  97. static void StopMsg(void)
  98. {
  99.     if (oldtimer != NULL)    {
  100.         setvect(TIMER, oldtimer);
  101.         oldtimer = NULL;
  102.     }
  103.     if (oldkeyboard != NULL)    {
  104.         setvect(KEYBOARDVECT, oldkeyboard);
  105.         oldkeyboard = NULL;
  106.     }
  107.     ClearClipboard();
  108.     ClearDialogBoxes();
  109.     restorecursor();    
  110.     unhidecursor();
  111.     hide_mousecursor();
  112. }
  113.  
  114. /* ------------ initialize the message system --------- */
  115. BOOL init_messages(void)
  116. {
  117.     AllocTesting = TRUE;
  118.     if (setjmp(AllocError) != 0)    {
  119.         StopMsg();
  120.         return FALSE;
  121.     }
  122.     resetmouse();
  123.     set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  124.     savecursor();
  125.     hidecursor();
  126.     px = py = -1;
  127.     pmx = pmy = -1;
  128.     mx = my = 0;
  129.     CaptureMouse = CaptureKeyboard = NULL;
  130.     NoChildCaptureMouse = FALSE;
  131.     NoChildCaptureKeyboard = FALSE;
  132.     MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
  133.     EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
  134.     if (oldtimer == NULL)    {
  135.         oldtimer = getvect(TIMER);
  136.         setvect(TIMER, newtimer);
  137.     }
  138.     if (oldkeyboard == NULL)    {
  139.         oldkeyboard = getvect(KEYBOARDVECT);
  140.         setvect(KEYBOARDVECT, newkeyboard);
  141.     }
  142.     setvect(CRIT, newcrit);
  143.     PostMessage(NULL,START,0,0);
  144.     lagdelay = FIRSTDELAY;
  145.     return TRUE;
  146. }
  147.  
  148. /* ----- post an event and parameters to event queue ---- */
  149. static void PostEvent(MESSAGE event, int p1, int p2)
  150. {
  151.     if (EventQueueCtr != MAXMESSAGES)    {
  152.         EventQueue[EventQueueOnCtr].event = event;
  153.         EventQueue[EventQueueOnCtr].mx = p1;
  154.         EventQueue[EventQueueOnCtr].my = p2;
  155.         if (++EventQueueOnCtr == MAXMESSAGES)
  156.             EventQueueOnCtr = 0;
  157.         EventQueueCtr++;
  158.     }
  159. }
  160.  
  161. /* ------ collect mouse, clock, and keyboard events ----- */
  162. static void near collect_events(void)
  163. {
  164.     static int ShiftKeys = 0;
  165.     int sk;
  166.     struct tm *now;
  167.     static BOOL flipflop = FALSE;
  168.     static char timestr[9];
  169.     int hr;
  170.  
  171.     /* -------- test for a clock event (one/second) ------- */
  172.     if (timed_out(clocktimer))    {
  173.         /* ----- get the current time ----- */
  174.         time_t t = time(NULL);
  175.         now = localtime(&t);
  176.         hr = now->tm_hour > 12 ?
  177.              now->tm_hour - 12 :
  178.              now->tm_hour;
  179.         if (hr == 0)
  180.             hr = 12;
  181.         sprintf(timestr, "%2d:%02d", hr, now->tm_min);
  182.         strcpy(timestr+5, now->tm_hour > 11 ? "pm " : "am ");
  183.         /* ------- blink the : at one-second intervals ----- */
  184.         if (flipflop)
  185.             *(timestr+2) = ' ';
  186.         flipflop ^= TRUE;
  187.         /* -------- reset the timer -------- */
  188.         set_timer(clocktimer, 1);
  189.         /* -------- post the clock event -------- */
  190.         PostEvent(CLOCKTICK, FP_SEG(timestr), FP_OFF(timestr));
  191.     }
  192.  
  193.     /* --------- keyboard events ---------- */
  194.     if ((sk = getshift()) != ShiftKeys)    {
  195.         ShiftKeys = sk;
  196.         /* ---- the shift status changed ---- */
  197.         PostEvent(SHIFT_CHANGED, sk, 0);
  198.     }
  199.  
  200.     /* ---- build keyboard events for key combinations that
  201.         BIOS doesn't report --------- */
  202.     if (sk & ALTKEY)    {
  203.         if (keyportvalue == 14)    {
  204.             waitforkeyboard();
  205.             PostEvent(KEYBOARD, ALT_BS, sk);
  206.         }
  207.         if (keyportvalue == 83)    {
  208.             waitforkeyboard();
  209.             PostEvent(KEYBOARD, ALT_DEL, sk);
  210.         }
  211.     }
  212.     if (sk & CTRLKEY)    {
  213.         if (keyportvalue == 82)    {
  214.             while (!(inp(0x60) & 0x80))
  215.             waitforkeyboard();
  216.             PostEvent(KEYBOARD, CTRL_INS, sk);
  217.         }
  218.     }
  219.     /* ----------- test for keystroke ------- */
  220.     if (keyhit())    {
  221.         static int cvt[] = {SHIFT_INS,END,DN,PGDN,BS,'5',
  222.                         FWD,HOME,UP,PGUP};
  223.         int c = getkey();
  224.  
  225.         /* -------- convert numeric pad keys ------- */
  226.         if (sk & (LEFTSHIFT | RIGHTSHIFT))    {
  227.             if (c >= '0' && c <= '9')
  228.                 c = cvt[c-'0'];
  229.             else if (c == '.' || c == DEL)
  230.                 c = SHIFT_DEL;
  231.             else if (c == INS)
  232.                 c = SHIFT_INS;
  233.         }
  234.         if (c != '\r' && (c < ' ' || c > 127))
  235.             clearBIOSbuffer();
  236.         /* ------ post the keyboard event ------ */
  237.         PostEvent(KEYBOARD, c, sk);
  238.     }
  239.  
  240.     /* ------------ test for mouse events --------- */
  241.     if (button_releases())    {
  242.         /* ------- the button was released -------- */
  243.         doubletimer = DOUBLETICKS;
  244.         PostEvent(BUTTON_RELEASED, mx, my);
  245.         disable_timer(delaytimer);
  246.     }
  247.     get_mouseposition(&mx, &my);
  248.     if (mx != px || my != py)  {
  249.         px = mx;
  250.         py = my;
  251.         PostEvent(MOUSE_MOVED, mx, my);
  252.     }
  253.     if (rightbutton())
  254.         PostEvent(RIGHT_BUTTON, mx, my);
  255.     if (leftbutton())    {
  256.         if (mx == pmx && my == pmy)    {
  257.             /* ---- same position as last left button ---- */
  258.             if (timer_running(doubletimer))    {
  259.                 /* -- second click before double timeout -- */
  260.                 disable_timer(doubletimer);
  261.                 PostEvent(DOUBLE_CLICK, mx, my);
  262.             }
  263.             else if (!timer_running(delaytimer))    {
  264.                 /* ---- button held down a while ---- */
  265.                 delaytimer = lagdelay;
  266.                 lagdelay = DELAYTICKS;
  267.                 /* ---- post a typematic-like button ---- */
  268.                 PostEvent(LEFT_BUTTON, mx, my);
  269.             }
  270.         }
  271.         else    {
  272.             /* --------- new button press ------- */
  273.             disable_timer(doubletimer);
  274.             delaytimer = FIRSTDELAY;
  275.             lagdelay = DELAYTICKS;
  276.             PostEvent(LEFT_BUTTON, mx, my);
  277.             pmx = mx;
  278.             pmy = my;
  279.         }
  280.     }
  281.     else
  282.         lagdelay = FIRSTDELAY;
  283. }
  284.  
  285. /* ----- post a message and parameters to msg queue ---- */
  286. void PostMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  287. {
  288.     if (msg == ENDDIALOG)    {
  289.         msg++;
  290.         --msg;
  291.     }
  292.     if (MsgQueueCtr != MAXMESSAGES)    {
  293.         MsgQueue[MsgQueueOnCtr].wnd = wnd;
  294.         MsgQueue[MsgQueueOnCtr].msg = msg;
  295.         MsgQueue[MsgQueueOnCtr].p1 = p1;
  296.         MsgQueue[MsgQueueOnCtr].p2 = p2;
  297.         if (++MsgQueueOnCtr == MAXMESSAGES)
  298.             MsgQueueOnCtr = 0;
  299.         MsgQueueCtr++;
  300.     }
  301. }
  302.  
  303. /* --------- send a message to a window ----------- */
  304. int SendMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  305. {
  306.     int rtn = TRUE, x, y;
  307.  
  308. #ifdef INCLUDE_LOGGING
  309.     LogMessages(wnd, msg, p1, p2);
  310. #endif
  311.     if (wnd != NULL)
  312.         switch (msg)    {
  313.             case PAINT:
  314.             case BORDER:
  315.                 /* ------- don't send these messages unless the
  316.                     window is visible -------- */
  317.                 if (isVisible(wnd))
  318.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  319.                 break;
  320.             case RIGHT_BUTTON:
  321.             case LEFT_BUTTON:
  322.             case DOUBLE_CLICK:
  323.             case BUTTON_RELEASED:
  324.                 /* --- don't send these messages unless the
  325.                     window is visible or has captured the mouse -- */
  326.                 if (isVisible(wnd) || wnd == CaptureMouse)
  327.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  328.                 break;
  329.             case KEYBOARD:
  330.             case SHIFT_CHANGED:
  331.                 /* ------- don't send these messages unless the
  332.                     window is visible or has captured the keyboard -- */
  333.                 if (!(isVisible(wnd) || wnd == CaptureKeyboard))
  334.                     break;
  335.             default:
  336.                 rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  337.                 break;
  338.         }
  339.     /* ----- window processor returned true or the message was sent
  340.         to no window at all (NULL) ----- */
  341.     if (rtn != FALSE)    {
  342.         /* --------- process messages that a window sends to the
  343.             system itself ---------- */
  344.         switch (msg)    {
  345.             case STOP:
  346.                 StopMsg();
  347.                 break;
  348.             /* ------- clock messages --------- */
  349.             case CAPTURE_CLOCK:
  350.                 Cwnd = wnd;
  351.                 set_timer(clocktimer, 0);
  352.                 break;
  353.             case RELEASE_CLOCK:
  354.                 Cwnd = NULL;
  355.                 disable_timer(clocktimer);
  356.                 break;
  357.             /* -------- keyboard messages ------- */
  358.             case KEYBOARD_CURSOR:
  359.                 if (wnd == NULL)
  360.                     cursor((int)p1, (int)p2);
  361.                 else if (wnd == inFocus)
  362.                     cursor(GetClientLeft(wnd)+(int)p1,
  363.                                 GetClientTop(wnd)+(int)p2);
  364.                 break;
  365.             case CAPTURE_KEYBOARD:
  366.                 if (p2)
  367.                     ((WINDOW)p2)->PrevKeyboard=CaptureKeyboard;
  368.                 else
  369.                     wnd->PrevKeyboard = CaptureKeyboard;
  370.                 CaptureKeyboard = wnd;
  371.                 NoChildCaptureKeyboard = (int)p1;
  372.                 break;
  373.             case RELEASE_KEYBOARD:
  374.                 if (wnd != NULL)    {
  375.                     if (CaptureKeyboard == wnd || (int)p1)
  376.                         CaptureKeyboard = wnd->PrevKeyboard;
  377.                     else    {
  378.                         WINDOW twnd = CaptureKeyboard;
  379.                         while (twnd != NULL)    {
  380.                             if (twnd->PrevKeyboard == wnd)    {
  381.                                 twnd->PrevKeyboard = wnd->PrevKeyboard;
  382.                                 break;
  383.                             }
  384.                             twnd = twnd->PrevKeyboard;
  385.                         }
  386.                         if (twnd == NULL)
  387.                             CaptureKeyboard = NULL;
  388.                     }
  389.                     wnd->PrevKeyboard = NULL;
  390.                 }
  391.                 else
  392.                     CaptureKeyboard = NULL;
  393.                 NoChildCaptureKeyboard = FALSE;
  394.                 break;
  395.             case CURRENT_KEYBOARD_CURSOR:
  396.                 curr_cursor(&x, &y);
  397.                 *(int*)p1 = x;
  398.                 *(int*)p2 = y;
  399.                 break;
  400.             case SAVE_CURSOR:
  401.                 savecursor();
  402.                 break;
  403.             case RESTORE_CURSOR:
  404.                 restorecursor();
  405.                 break;
  406.             case HIDE_CURSOR:
  407.                 normalcursor();
  408.                 hidecursor();
  409.                 break;
  410.             case SHOW_CURSOR:
  411.                 if (p1)
  412.                     set_cursor_type(0x0106);
  413.                 else
  414.                     set_cursor_type(0x0607);
  415.                 unhidecursor();
  416.                 break;
  417.             case WAITKEYBOARD:
  418.                 waitforkeyboard();
  419.                 break;
  420.             /* -------- mouse messages -------- */
  421.             case RESET_MOUSE:
  422.                 resetmouse();
  423.                 set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  424.                 break;
  425.             case MOUSE_INSTALLED:
  426.                 rtn = mouse_installed();
  427.                 break;
  428.             case MOUSE_TRAVEL:    {
  429.                 RECT rc;
  430.                 if (!p1)    {
  431.                     rc.lf = rc.tp = 0;
  432.                     rc.rt = SCREENWIDTH-1;
  433.                     rc.bt = SCREENHEIGHT-1;
  434.                 }
  435.                 else 
  436.                     rc = *(RECT *)p1;
  437.                 set_mousetravel(rc.lf, rc.rt, rc.tp, rc.bt);
  438.                 break;
  439.             }
  440.             case SHOW_MOUSE:
  441.                 show_mousecursor();
  442.                 break;
  443.             case HIDE_MOUSE:
  444.                 hide_mousecursor();
  445.                 break;
  446.             case MOUSE_CURSOR:
  447.                 set_mouseposition((int)p1, (int)p2);
  448.                 break;
  449.             case CURRENT_MOUSE_CURSOR:
  450.                 get_mouseposition((int*)p1,(int*)p2);
  451.                 break;
  452.             case WAITMOUSE:
  453.                 waitformouse();
  454.                 break;
  455.             case TESTMOUSE:
  456.                 rtn = mousebuttons();
  457.                 break;
  458.             case CAPTURE_MOUSE:
  459.                 if (p2)
  460.                     ((WINDOW)p2)->PrevMouse = CaptureMouse;
  461.                 else
  462.                     wnd->PrevMouse = CaptureMouse;
  463.                 CaptureMouse = wnd;
  464.                 NoChildCaptureMouse = (int)p1;
  465.                 break;
  466.             case RELEASE_MOUSE:
  467.                 if (wnd != NULL)    {
  468.                     if (CaptureMouse == wnd || (int)p1)
  469.                         CaptureMouse = wnd->PrevMouse;
  470.                     else    {
  471.                         WINDOW twnd = CaptureMouse;
  472.                         while (twnd != NULL)    {
  473.                             if (twnd->PrevMouse == wnd)    {
  474.                                 twnd->PrevMouse = wnd->PrevMouse;
  475.                                 break;
  476.                             }
  477.                             twnd = twnd->PrevMouse;
  478.                         }
  479.                         if (twnd == NULL)
  480.                             CaptureMouse = NULL;
  481.                     }
  482.                     wnd->PrevMouse = NULL;
  483.                 }
  484.                 else
  485.                     CaptureMouse = NULL;
  486.                 NoChildCaptureMouse = FALSE;
  487.                 break;
  488.             default:
  489.                 break;
  490.         }
  491.     }
  492.     return rtn;
  493. }
  494.  
  495. static RECT VisibleRect(WINDOW wnd)
  496. {
  497.     RECT rc = WindowRect(wnd);
  498.     if (!TestAttribute(wnd, NOCLIP))    {
  499.         WINDOW pwnd = GetParent(wnd);
  500.         RECT prc;
  501.         prc = ClientRect(pwnd);
  502.         while (pwnd != NULL)    {
  503.             if (TestAttribute(pwnd, NOCLIP))
  504.                 break;
  505.             rc = subRectangle(rc, prc);
  506.             if (!ValidRect(rc))
  507.                 break;
  508.             if ((pwnd = GetParent(pwnd)) != NULL)
  509.                 prc = ClientRect(pwnd);
  510.         }
  511.     }
  512.     return rc;
  513. }
  514.  
  515. /* ----- find window that mouse coordinates are in --- */
  516. static WINDOW inWindow(WINDOW wnd, int x, int y)
  517. {
  518.     WINDOW Hit = NULL;
  519.     while (wnd != NULL)    {
  520.         if (isVisible(wnd))    {
  521.             WINDOW wnd1;
  522.             RECT rc = VisibleRect(wnd);
  523.             if (InsideRect(x, y, rc))
  524.                 Hit = wnd;
  525.             if ((wnd1 = inWindow(LastWindow(wnd), x, y)) != NULL)
  526.                 Hit = wnd1;
  527.             if (Hit != NULL)
  528.                 break;
  529.         }
  530.         wnd = PrevWindow(wnd);
  531.     }
  532.     return Hit;
  533. }
  534.  
  535. static WINDOW MouseWindow(int x, int y)
  536. {
  537.     /* ------ get the window in which a
  538.                     mouse event occurred ------ */
  539.     WINDOW Mwnd = inWindow(ApplicationWindow, x, y);
  540.     /* ---- process mouse captures ----- */
  541.     if (CaptureMouse != NULL)    {
  542.         if (NoChildCaptureMouse ||
  543.                 Mwnd == NULL     ||
  544.                     !isAncestor(Mwnd, CaptureMouse))
  545.             Mwnd = CaptureMouse;
  546.     }
  547.     return Mwnd;
  548. }
  549.  
  550. void handshake(void)
  551. {
  552.     handshaking++;
  553.     dispatch_message();
  554.     --handshaking;
  555. }
  556.  
  557. /* ---- dispatch messages to the message proc function ---- */
  558. BOOL dispatch_message(void)
  559. {
  560.     WINDOW Mwnd, Kwnd;
  561.     /* -------- collect mouse and keyboard events ------- */
  562.     collect_events();
  563.     /* --------- dequeue and process events -------- */
  564.     while (EventQueueCtr > 0)  {
  565.         struct events ev;
  566.             
  567.         ev = EventQueue[EventQueueOffCtr];
  568.         if (++EventQueueOffCtr == MAXMESSAGES)
  569.             EventQueueOffCtr = 0;
  570.         --EventQueueCtr;
  571.  
  572.         /* ------ get the window in which a
  573.                         keyboard event occurred ------ */
  574.         Kwnd = inFocus;
  575.  
  576.         /* ---- process keyboard captures ----- */
  577.         if (CaptureKeyboard != NULL)
  578.             if (Kwnd == NULL ||
  579.                     NoChildCaptureKeyboard ||
  580.                         !isAncestor(Kwnd, CaptureKeyboard))
  581.                 Kwnd = CaptureKeyboard;
  582.  
  583.         /* -------- send mouse and keyboard messages to the
  584.             window that should get them -------- */
  585.         switch (ev.event)    {
  586.             case SHIFT_CHANGED:
  587.             case KEYBOARD:
  588.                 if (!handshaking)
  589.                     SendMessage(Kwnd, ev.event, ev.mx, ev.my);
  590.                 break;
  591.             case LEFT_BUTTON:
  592.                 if (!handshaking)    {
  593.                     Mwnd = MouseWindow(ev.mx, ev.my);
  594.                     if (!CaptureMouse ||
  595.                             (!NoChildCaptureMouse &&
  596.                                 isAncestor(Kwnd, CaptureKeyboard)))
  597.                         if (Mwnd != inFocus)
  598.                             SendMessage(Mwnd, SETFOCUS, TRUE, 0);
  599.                     SendMessage(Mwnd, LEFT_BUTTON, ev.mx, ev.my);
  600.                 }
  601.                 break;
  602.             case BUTTON_RELEASED:
  603.             case DOUBLE_CLICK:
  604.             case RIGHT_BUTTON:
  605.                 if (handshaking)
  606.                     break;
  607.             case MOUSE_MOVED:
  608.                 Mwnd = MouseWindow(ev.mx, ev.my);
  609.                 SendMessage(Mwnd, ev.event, ev.mx, ev.my);
  610.                 break;
  611.             case CLOCKTICK:
  612.                 SendMessage(Cwnd, ev.event,
  613.                     (PARAM) MK_FP(ev.mx, ev.my), 0);
  614.                 break;
  615.             default:
  616.                 break;
  617.         }
  618.     }
  619.     /* ------ dequeue and process messages ----- */
  620.     while (MsgQueueCtr > 0)  {
  621.         struct msgs mq;
  622.  
  623.         mq = MsgQueue[MsgQueueOffCtr];
  624.         if (++MsgQueueOffCtr == MAXMESSAGES)
  625.             MsgQueueOffCtr = 0;
  626.         --MsgQueueCtr;
  627.         SendMessage(mq.wnd, mq.msg, mq.p1, mq.p2);
  628.         if (mq.msg == ENDDIALOG)
  629.             return FALSE;
  630.         if (mq.msg == STOP)
  631.             return FALSE;
  632.     }
  633.     return TRUE;
  634. }
  635.  
  636.